package com.allen.admin.config.shiro;

import com.allen.admin.service.common.domain.AdminRole;
import com.allen.admin.service.common.domain.AdminRolePerm;
import com.allen.admin.service.common.domain.AdminUser;
import com.allen.admin.service.common.service.AdminRolePermService;
import com.allen.admin.service.common.service.AdminRoleService;
import com.allen.admin.service.common.service.AdminUserService;
import com.xxx.config.ModelResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.util.List;

/**
 *
 * @author xiaoqing.chen
 *
 */
public class ShiroRealm extends AuthorizingRealm {

	private static final Logger logger = LoggerFactory.getLogger(ShiroRealm.class);

	@Autowired
	@Qualifier("adminUserServiceClient")
	private AdminUserService adminUserService;
	@Autowired
	@Qualifier("adminRoleServiceClient")
	private AdminRoleService adminRoleService;
	@Autowired
	@Qualifier("adminRolePermServiceClient")
	private AdminRolePermService adminRolePermService;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String account = String.valueOf(principals.getPrimaryPrincipal());

        ModelResult<AdminUser> model = adminUserService.query(account);
        final AdminUser user = model.getModel();

        List<Integer> roleIds = user.roleIdsList();
        if (CollectionUtils.isEmpty(roleIds)) {
        	return authorizationInfo;
        }

        ModelResult<List<AdminRole>> modelResult = adminRoleService.query(roleIds);
        if (!modelResult.isSuccess()) {
        	return authorizationInfo;
        }

        final List<AdminRole> roles = modelResult.getModel();
        if (CollectionUtils.isEmpty(roles)) {
        	return authorizationInfo;
        }

        for (AdminRole role : roles) {

        	if (AdminRole.STATUS_DISABLED == role.getStatus()) {
        		continue;
        	}

            // 添加角色
            authorizationInfo.addRole(role.getCode());

            ModelResult<List<AdminRolePerm>> permResult = adminRolePermService.query(role.getId());
            if (!permResult.isSuccessAndLogError()) {
            	continue;
            }
            if (CollectionUtils.isEmpty(permResult.getModel())) {
            	continue;
            }

            final List<AdminRolePerm> perms = permResult.getModel();
            for (AdminRolePerm perm : perms) {
            	// 添加权限
                authorizationInfo.addStringPermission(perm.getPermCode());
            }
        }

        return authorizationInfo;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {

		String username = String.valueOf(token.getPrincipal());
		String password = new String((char[]) token.getCredentials());

		// 通过数据库进行验证
		ModelResult<AdminUser> model;
		try {
			model = adminUserService.query(username, password);
		} catch (Exception e) {
			logger.error("账号校验异常", e);
			throw new AuthenticationException("账号校验异常, 请联系管理员.");
		}
		final AdminUser user = model.getModel();

		if (user == null) {
			throw new AuthenticationException("用户名或密码错误.");
		}

		if (AdminUser.STATUS_ENABLED != user.getStatus()) {

			if (AdminUser.STATUS_DISABLED == user.getStatus()) {
				throw new AuthenticationException("账号已被禁用, 请联系管理员.");
			} else if (AdminUser.STATUS_FORMER == user.getStatus()) {
				throw new AuthenticationException("账号无法使用, 请联系管理员.");
			} else {
				throw new AuthenticationException("账号状态异常, 请联系管理员.");
			}

		}

		SimpleAuthenticationInfo authenticationInfo =
				new SimpleAuthenticationInfo(username, password, getName());

		return authenticationInfo;
	}

}
